#pragma once

#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sendfile.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <strings.h>
#include <sstream>
#include <vector>
#include <unordered_map>
#include "Log.hpp"

#define BACKLOG 5

class Sock{
    public:
        /*因为这里是对外的接口类方法，因此需要申明为static*/
        static int Socket()
      {
            int sock = socket(AF_INET,SOCK_STREAM,0);
            if(sock <0)
            {
                LOG(Fatal,"socket creat error");
            }
            return sock;
        }
        static void Bind(int sock,int port)
        {
            struct sockaddr_in local;
            bzero(&local,sizeof(local));

            local.sin_family = AF_INET;
            local.sin_port = htons(port);
            local.sin_addr.s_addr = htonl(INADDR_ANY);
            if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)
            {
                LOG(Fatal,"socket bind error");
                exit(BindErr);
            }

        }
        static void Listen(int sock)
        {
            if(listen(sock,BACKLOG)<0)
            {
                LOG(Fatal,"socket listen error");
                exit(ListenErr);
            }
        }
        static void SetSockOpt(int sock)
        {
            int opt = 1;
            setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));

        }
        static int Accept(int sock)
        {
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            int s = accept(sock,(struct sockaddr*)&peer,&len);
            if(s<0)
            {
                LOG(Warning,"accept error");
            }
            return s;
        }
        static void GetLine(int sock,std::string &line)
        {
            //这里将\n,\r,\r\n转换为-》\n
            char c = 'X';
            while(c != '\n')
            {
                ssize_t s = recv(sock,&c,1,0);
                if(s > 0)
                {
                    if(c == '\r')
                    {
                        ssize_t ss = recv(sock,&c,1,MSG_PEEK);
                        if(ss > 0&& c=='\n')
                        {
                            //\r\n的情况
                            recv(sock,&c,1,0); 
                        }
                        else{
                            //\r的情况
                            c = '\n';
                        }
                    }
                    //有三种情况：1：读取到的内容是常规字符
                    //2：\n
                    //3:\r,\r\n转换为->\n
                    line.push_back(c);
                }
            }
        }
};
